#include <iostream>
#include <memory>
#include <vector>
#include <algorithm>
#include <regex>
#include <set>

// 解释器模式，给定一个语言，定义这个语言文法的一种表示，并定义一个解释器，这个解释器使用该表示来解释语言中的句子

// 抽象表达式类，声明一个抽象的解释操作，这个接口为抽象语法树中的所有的节点共享
class Expression {
    public:
    virtual bool Interpret(const std::string& info) = 0;
};

// 终结符表达式类，实现与语法中的终结符相关联的解释操作
class TerminalExpression : public Expression {
    public:
    TerminalExpression(const std::vector<std::string> datas) {
        infos_.insert(datas.begin(),datas.end());
    }

    bool Interpret(const std::string& info) override {
        if(infos_.find(info) != infos_.end()) {
            return true;
        }
        return false;
    }

    private:
    std::set<std::string> infos_;
};

// 非终结符表达式类，为文法总的非终结符实现解释操作，对文法中的每一条规则R1,R2...都需要一个具体的非终结符表达式类
// 通过实现抽象表达式的interpret()方法实现解释操作，解释操作以递归方式调用上面所提到的代表R1,R2...中各个符号的实例遍历
class AndExpression : public Expression {
    public:
    AndExpression(std::shared_ptr<Expression> city,std::shared_ptr<Expression> person):smartCity_(city),smartPerson_(person) {}
    bool Interpret(const std::string& info) {
        std::regex pattern("的");
        std::vector<std::string> results(std::sregex_token_iterator(info.begin(),info.end(),pattern,-1),std::sregex_token_iterator());
        if(results.size() != 2) {
            std::cout << "输入解释信息有误，无法解析" << std::endl;
            return false;
        }
        return smartCity_->Interpret(results[0]) && smartPerson_->Interpret(results[1]);
    }
    private:
    std::shared_ptr<Expression> smartCity_;
    std::shared_ptr<Expression> smartPerson_;
};

// 上下文全局信息类，包括解释器之外的一些全局信息
class Context {
    public:
    Context() {
        citys_.push_back("成都");
        citys_.push_back("临沂");
        persons_.push_back("老人");
        persons_.push_back("小孩");
        smartAndExpr = std::make_shared<AndExpression>(std::make_shared<TerminalExpression>(citys_),std::make_shared<TerminalExpression>(persons_));
    }

    void IsFree(const std::string& info) {
        if(smartAndExpr->Interpret(info)) {
            std::cout << info << "， 您本次乘车免费" << std::endl;
        }
        else {
            std::cout << info << "， 您本次乘车扣费2元" << std::endl;

        }
    }
    private:
    std::vector<std::string> citys_;
    std::vector<std::string> persons_;
    std::shared_ptr<Expression> smartAndExpr;
};

int main () {
    std::cout << "hello，解释器模式" << std::endl;
    
    std::shared_ptr<Context> bus = std::make_shared<Context>();
    std::vector<std::string> passengers = {"成都的老人","成都的年轻人","成都的小孩","临沂的老人","临沂的年轻人","临沂的儿童"};
    for(std::string passenger : passengers) {
        bus->IsFree(passenger);
    }

    return 0;
}